
/*----------- app_led.c -----------*/
#include "main.h"
#include "app_led.h"

extern TIM_HandleTypeDef htim4;
/* 硬件PWM配置 */
#define LED_PWM_TIMER       &htim4
#define LED_PWM_CHANNEL     TIM_CHANNEL_2
#define LED_PWM_MAX         100      // 对应ARR值

typedef struct {
    app_led_state_t state;
    uint16_t breathe_step;     // 呼吸相位步进
    uint16_t blink_counter;    // 闪烁计数器
    uint8_t current_duty;      // 当前PWM占空比
} app_led_ctrl_t;

static app_led_ctrl_t led = {
    .state = APP_LED_STATE_STANDBY,
    .breathe_step = 0,
    .blink_counter = 0,
    .current_duty = 0
};

/* 时间单位转换 */
#define BREATHE_STEPS   (BREATHE_PERIOD_MS / 10)
#define BLINK_ON_STEPS  (BLINK_ON_MS / 10)
#define BLINK_OFF_STEPS (BLINK_OFF_MS / 10)

void app_led_init(void) 
{
    HAL_TIM_PWM_Start(LED_PWM_TIMER, LED_PWM_CHANNEL);
    __HAL_TIM_SET_COMPARE(LED_PWM_TIMER, LED_PWM_CHANNEL, LED_PWM_MAX);
}

void app_led_set_state(app_led_state_t state) 
{
    if(led.state == state)
    {
        return;
    }
    if(state < APP_LED_STATE_COUNT) {
        led.state = state;
        led.breathe_step = 0;
        led.blink_counter = 0;
    }
}

void app_led_task_10ms(void) 
{
    uint8_t new_duty = 0;
    
    switch(led.state) {
        case APP_LED_STATE_STANDBY:
            new_duty = LED_PWM_MAX;
            break;

        case APP_LED_STATE_NORMAL: 
        {
            /* 线性呼吸算法 */
            const uint16_t half_steps = BREATHE_STEPS / 2;
            
            if(++led.breathe_step >= BREATHE_STEPS) 
            {
                led.breathe_step = 0;
            }

            if(led.breathe_step < half_steps) 
            {
                // 上升阶段：0% → 100%
                new_duty = (LED_PWM_MAX * led.breathe_step) / half_steps;
            } 
            else 
            {
                // 下降阶段：100% → 0%
                uint16_t decay_step = led.breathe_step - half_steps;
                new_duty = LED_PWM_MAX - (LED_PWM_MAX * decay_step) / half_steps;
            }
            break;
        }

        case APP_LED_STATE_ERROR:
            if(++led.blink_counter >= (BLINK_ON_STEPS + BLINK_OFF_STEPS)) 
            {
                led.blink_counter = 0;
            }
            new_duty = (led.blink_counter < BLINK_ON_STEPS) ? LED_PWM_MAX : 0;
            break;

        default:
            new_duty = 0;
            break;
    }

    /* 更新PWM输出 */
    if(new_duty != led.current_duty) 
    {
        __HAL_TIM_SET_COMPARE(LED_PWM_TIMER, LED_PWM_CHANNEL, new_duty);
        led.current_duty = new_duty;
    }
}
